<template>
  <div class="wrap">
    <template>
      <!--标准-->
      <div class="item select-item">
        <span class="text-ellipsis"
              :title="$t('message.FastenerDesign.Standard')">
          {{$t('message.FastenerDesign.Standard')}}：
        </span>
        <select class="flex-grow-1"
                v-model="curStandard"
                :title="curStandard">
          <option v-for="(item,index) in standardList" :key="index">{{item}}</option>
        </select>
      </div>
      <!--分类-->
      <div class="item select-item">
        <span class="text-ellipsis"
              :title="$t('message.FastenerDesign.Category')">
          {{$t('message.FastenerDesign.Category')}}：
        </span>
        <select class="flex-grow-1"
                v-model="curCategory"
                :title="curCategory">
          <option v-for="(item,index) in categoryList" :key="index" :value="item">{{item}}
          </option>
        </select>
      </div>
      <!--类型-->
      <div class="item select-item">
        <span class="text-ellipsis"
              :title="$t('message.FastenerDesign.Class')">
          {{$t('message.FastenerDesign.Class')}}：
        </span>
        <select class="flex-grow-1"
                v-model="curClass"
                :title="curClass">
          <option v-for="(item,index) in classList" :key="index" :value="item">{{item}}</option>
        </select>
      </div>
      <!--零件-->
      <div class="item select-item">
        <span class="text-ellipsis"
              :title="$t('message.FastenerDesign.Part')">
          {{$t('message.FastenerDesign.Part')}}：
        </span>
        <select class="flex-grow-1"
                v-model="curComponent"
                :title="curComponent">
          <option v-for="(item,index) in componentList" :key="index" :value="item">{{item.name}}</option>
        </select>
      </div>
      <!--零件参数-->
      <div v-if="primaryAttribute">
        <div class="item select-item">
          <span class="text-ellipsis"
                :title="getPrimaryAttributeAlias">
            {{ getPrimaryAttributeAlias }}：
          </span>
          <select class="flex-grow-1"
                  v-model="selected.primary"
                  :title="selected.primary"
                  @change="changeSelectEventHandler('primary')">
            <option v-for="(op,index) in primaryAttribute.options" :key="index" :value="op">{{ op }}</option>
          </select>
        </div>
        <div class="item select-item" v-for="(attribute,index) in attributes" :key="index">
          <span class="text-ellipsis"
                :title="attribute.alias">
            {{ attribute.alias }}：
          </span>
          <select v-if="!attribute.isInput" class="flex-grow-1"
                  v-model="selected[attribute.key]"
                  :title="selected[attributes.key]"
                  @change="changeSelectEventHandler(attribute.key)">
            <option v-for="(option,index) in getAttributeOptions(attribute.key)" :key="index" :value="option">{{ option }}</option>
          </select>
          <div v-else class="flex-grow-1">
            <el-input-number :max="getMaxValue(attribute)" :step="1" :min="getMinValue(attribute)"
                             v-model="selected[attribute.key]"/>
            <p class="attribute-unit">{{ attribute.unit }}</p>
          </div>
        </div>
      </div>
      <!--缩略图-->
      <div class="thumbnail">
        <img v-if="partInfo" class="thumbnail-img" :src="partInfo.thumbnail"/>
      </div>
      <!--位置-->
      <div>
        <template class="d-flex align-items-center">
          <p><b>{{ $t('message.FastenerDesign.position') }}</b></p>
        </template>
        <template class="d-flex align-items-center">
          <query-list
                  :tipMsg="$t('message.FastenerDesign.posInfo')"
                  v-model="params.position"
                  :active="params.queryListActiveMap.position"
                  @removeItem="removeSelect"
                  @switchQuery="switchQuery('position')"/>
        </template>
      </div>
      <!--对齐方向-->
      <div>
        <template class="d-flex align-items-center">
          <p><b>{{ $t('message.FastenerDesign.alignmentDirection') }}</b></p>
        </template>
        <template class="d-flex align-items-center">
          <query-list
                  :tipMsg="$t('message.FastenerDesign.dirInfo')"
                  v-model="params.direction"
                  :active="params.queryListActiveMap.direction"
                  @removeItem="removeSelect"
                  @switchQuery="switchQuery('direction')"/>
        </template>
      </div>
      <!--对齐轴-->
      <div class="d-flex align-items-center">
        <label class="el-form-item__label">{{$t('message.FastenerDesign.alignAxis')}}：</label>
        <el-radio v-model="params.alignmentDir" :label="'x'" @change="changeCommon">{{$t('message.FastenerDesign.xAxis')}}</el-radio>
        <el-radio v-model="params.alignmentDir" :label="'y'" @change="changeCommon">{{$t('message.FastenerDesign.yAxis')}}</el-radio>
        <el-radio v-model="params.alignmentDir" :label="'z'" @change="changeCommon">{{$t('message.FastenerDesign.zAxis')}}</el-radio>
      </div>
      <!--方向（是否反向）-->
      <div class="d-flex align-items-center">
        <label class="el-form-item__label">{{$t('message.FastenerDesign.direction')}}：</label>
        <el-checkbox v-model="params.reverseDirection" :label="$t('message.FastCutCmd.reverseDir')" @change="changeCommon"/>
      </div>
      <!--偏移距离-->
      <div class="d-flex align-items-center">
        <label class="el-form-item__label">{{$t('message.FastenerDesign.distance')}}：</label>
        <base-input-number v-model="params.offsetDistance" @change="changeCommon"/>
      </div>
    </template>
    <div class="btn">
      <!--确定-->
      <el-button type="primary" size="small" :disabled="isDisabled()" @click="confirm">
        {{ $t('message.HoleCmd.confirm') }}
      </el-button>
      <!--关闭-->
      <el-button size="small" @click="close">
        {{ $t('message.HoleCmd.close') }}
      </el-button>
    </div>
  </div>
</template>
<script>
  import DialogMixin from "../DialogMixin";
  import {fastenerDesignCommand} from "../../../Command/FastenerDesignCommand";
  import {ElementType, EntityType, GeomType} from "../../../modeling/TypeDefine";

  export default {
    mixins: [DialogMixin],
    name: 'CmdDlgFastenerDesign',
    data: function () {
      return {
        standardList: [],
        categoryList: [],
        classList: [],
        componentList: [],
        curStandard: null,
        curCategory: null,
        curClass: null,
        curComponent: null,
        partInfo: null,
        primaryAttribute: null,
        attributes: {},
        selected: {
          primary: ''
        },
        optionsValue: {},
        levelNames: [],
        levelInfo: [],
        params: {
          position: [],
          direction: [],
          queryListActiveMap: {
            direction: 1,
            position: 0,
          },
          reverseDirection: false,
          alignmentDir: "x",
          offsetDistance: 0,
        },
        count: 0,
        originValue: 1,
      }
    },
    methods: {
      isDisabled() {
        if (this.params.position.length === 0 || this.params.direction.length === 0) {
          return true;
        } else {
          return false;
        }
      },
      //初始化
      init() {
        this.switchQuery("position");
        this.primaryAttribute = null;
        this.attributes = {};
        let params = {
          url: '/stdlib/standard/'
        }
        fastenerDesignCommand.axiosRequest(params, data => {
          if(data && data.length > 0){
              this.standardList.length = 0;
              data?.forEach(e => this.standardList.push(e));
              this.curStandard = this.standardList[0];
          }
        })
      },
      //更新 把选中的信息传递给属性组件
      update() {
        this.optionsValue = {};
        this.optionsValue[this.primaryAttribute.alias] = this.selected.primary;

        // 遍历attribute列表拿到所有的属性的别名及对应的值，构建OptionValue
        Object.keys(this.attributes).forEach(attrKey => {
          this.optionsValue[this.attributes[attrKey].alias] = this.selected[attrKey];
        });
      },
      //根据当前选择的标准获取分类列表
      getCategoryName() {
        let formData = new Map();
        formData.set("standardName", this.curStandard);
        let params = {
          url: '/stdlib/category/',
          data: formData,
          isPost: true,
        }
        fastenerDesignCommand.axiosRequest(params, data => {
          if (data && data?.length > 0) {
            this.categoryList.length = 0;
            data?.forEach(category => {
              let allTypes = ["螺栓", "螺母", "螺钉", "螺柱", "键", "垫圈", "挡圈", "销", "密封圈", "铆钉"];
              if (allTypes.includes(category)) {
                this.categoryList.push(category)
              }
            });
            if (this.curCategory === this.categoryList[0]) {
              this.curCategory = this.categoryList[1]
            } else {
              this.curCategory = this.categoryList[0]
            }
          }
        });
      },
      //根据当前标准和分类获取类型列表
      getClassName() {
        if (this.curCategory != null) {
          let formData = new Map();
          formData.set("standardName", this.curStandard);
          formData.set("categoryName", this.curCategory);
          let params = {
            url: '/stdlib/getClassNamesByEntering/',
            data: formData,
            isPost: true,
          }
          fastenerDesignCommand.axiosRequest(params, data => {
              if(data && data.length > 0){
                  this.classList.length = 0;
                  data?.forEach(e => this.classList.push(e));
                  if (this.curClass === this.classList[0]) {
                      this.curClass = this.classList[1]
                  } else {
                      this.curClass = this.classList[0]
                  }
              }
          })
        }
      },
      //根据当前标准、分类、类型获取对应的零件列表
      getComponentInfo() {
        let url = '/stdlib/getComponentNamesByEntering';
        let formData = new Map();
        formData.set("standardName", this.curStandard);
        formData.set("categoryName", this.curCategory);
        formData.set("clsName", this.curClass);
        let params = {
          url: url,
          data: formData,
          isPost: true,
        }
        fastenerDesignCommand.axiosRequest(params, data => {
          if(data && data.length > 0){
              this.componentList.length = 0;
              data?.forEach(e => this.componentList.push(e));
              this.curComponent = this.componentList[0];
          }
        })
      },
      //获取零件的相关信息
      getComponentData() {
        let url = '/stdlib/getPartInfoByComponentName';
        let baseComponentParam = {
          standardName: this.curStandard,
          categoryName: this.curCategory,
          className: this.curClass,
          componentName: this.curComponent.name,
        }
        let params = {
          url: url,
          data: baseComponentParam,
          isFormData: false,
          isPost: true,
        }
        fastenerDesignCommand.axiosRequest(params, partInfo => {
          this.partInfo = partInfo;
        })
      },
      //执行紧固件装配命令
      exeCommand(preview) {
        if (this.params.position.length <= 0 && this.params.direction.length <= 0) {
          return;
        }
        //传递参数
        let params = {
          isPreview: preview,
          standardName: this.curStandard,
          category: this.curCategory,
          class: this.curClass,
          component: this.curComponent.name,
          optionsValue: this.optionsValue,
          materialInfo: this.getMaterialInfo(),
        }

        if (this.params.position.length > 0) {
          let obj = this.params.position[0];
          if (obj?.elementType === EntityType.EDGE) {//拾取的线
            params.selectInstance = obj;
          } else {//拾取点和基准点
            let position = obj?.position;
            params.insertPosition = position;
          }
        }

        if (this.params.direction.length > 0) {
          let selectIns = this.params.direction[0];
          params.selectObject = selectIns;
          params.alignmentDirection = this.params.alignmentDir;
        }
        params.reverseDir = this.params.reverseDirection;
        //偏移距离
        if (this.params.offsetDistance != 0) {
          params.offsetDistance = this.params.offsetDistance;
        }

        fastenerDesignCommand.executeFastenerCommand(params);
      },
      //解析零件属性
      parsePartInfo(partInfo) {
          if(partInfo){
              this.clearData();
              // 先解析其他属性 后面需要动态设置其他属性的值，所以必须保证在解析主属性之前其他属性是不能为空
              this.parserAttributes(partInfo);
              this.parserPrimaryAttribute(partInfo);
              // todo 先设置为第一个主属性
              this.selected.primary = this.primaryAttribute.options[0];
              this.changeSelectEventHandler("primary");
          }
      },
      //解析主要属性值
      parserPrimaryAttribute(partInfo) {
        let primaryAttribute = {};
        if (partInfo.primaryAttributeName && partInfo.columnAlias) {
          let keys = Object.keys(partInfo.columnAlias);
          let values = Object.values(partInfo.columnAlias);

          let targetIndex = values.indexOf(partInfo.primaryAttributeName);
          if (targetIndex !== -1) {
            let primaryAttributeKey = keys[targetIndex];
            primaryAttribute['alias'] = partInfo.primaryAttributeName;
            primaryAttribute['key'] = primaryAttributeKey;
            primaryAttribute['options'] = partInfo.secondaryAttributes.map(s => s.primaryAttributeValue);

            this.primaryAttribute = primaryAttribute;
            return;
          }
        }
        throw new Error("解析标准件主属性时出错");
      },
      //解析零件属性值
      parserAttributes(partInfo) {
        // 解析其他的属性值
        if (partInfo.secondaryAttributes && partInfo.columnAlias) {
          let keys = Object.keys(partInfo.columnAlias);
          let values = Object.values(partInfo.columnAlias);

          values.forEach((v, index) => {
            // 如果值等于主属性
            if (v === partInfo.primaryAttributeName) {
              return;
            }

            let attribute = {};
            let key = keys[index];
            attribute['key'] = key;
            attribute['alias'] = v;
            attribute['options'] = [];

            partInfo.secondaryAttributes.forEach(s => {
              // 去其他属性列表匹配对应的选项
              let targetAttribute = null;
              s.attributes.some(a => {
                for (let i = 0; i < a.length; i++) {
                  if (a[i].name === v) {
                    targetAttribute = a[i];
                    return true;
                  }
                }
                return false;
              });
              if (targetAttribute) {
                attribute['isInput'] = targetAttribute?.isInput;
                attribute['unit'] = targetAttribute?.unit;

                attribute.options.push({
                  primary: s.primaryAttributeValue,
                  options: targetAttribute.values
                })
              }
            });
            this.attributes[key] = attribute;
            this.$set(this.selected, key, "");
          })

        } else {
          throw new Error("解析其他属性时出错");
        }
      },
      //获取属性对应的参数值列表
      getAttributeOptions(key) {
        let index = this.attributes[key].options.findIndex(o => o.primary === this.selected.primary);
        if (index !== -1) {
          return this.attributes[key].options[index].options;
        } else {
          return [];
        }
      },
      //获取属性区间
      getAttributeRange(attribute) {
        // 获取当前选中的属性的索引值
        let targetIndex = attribute.options.findIndex(option => {
          return option.primary === this.selected.primary;
        });
        // 如果是一个区间，则这个属性的option有且只有一个，故取第一项的value
        let range = attribute.options[targetIndex].options[0];
        return range;
      },
      //获取属性区间值
      parseRangeValue(range, isMax) {
        let regx = /(?<min>^\d*)~(?<max>\d*)$/;
        let group = range.match(regx).groups;
        return isMax ? group.max : group.min;
      },
      //获取最大值
      getMaxValue(attribute) {
        let range = this.getAttributeRange(attribute);
        return this.parseRangeValue(range, true);
      },
      //获取最小值
      getMinValue(attribute) {
        let range = this.getAttributeRange(attribute);
        return this.parseRangeValue(range, false);
      },
      // resolver
      //解析材质信息
      parseComponentMaterialInfo() {
        this.levelInfo = [];
        if (!this.partInfo || !this.partInfo.materialInfo) {
          return;
        }

        let materialInfo = this.partInfo.materialInfo;
        let levelNames = Object.values(materialInfo.levelName);
        let curLevel = materialInfo.rootLevel;

        this.levelNames = levelNames;

        let startIndex = 0;
        if (this.equalPrimaryAttribute(levelNames[0])) {
          curLevel = this.getNextLevel(curLevel, Object.values(this.optionsValue));
          startIndex++;
        }

        // 解析等级规则数
        this.parseLevelTree(startIndex, curLevel);
      },
      //判断是否是同一个属性
      equalPrimaryAttribute(attrKey) {
        let aliasName = this.findAttributeAlias(attrKey);
        return aliasName === this.partInfo?.primaryAttributeName
      },
      findAttributeAlias(key) {
        return this.partInfo?.columnAlias[key];
      },
      // 解析等级规则数
      parseLevelTree(startIndex, curLevel) {
        // 匹配等级规则
        for (let i = startIndex; i < this.levelNames.length; i++) {
          let levelInfo = {
            name: this.levelNames[i],
            value: this.getCurLevelValue(curLevel),
            options: this.getLevelOptions(curLevel),
            nextLevelName: this.getNextLevelName(i),
            level: curLevel,
            isMaterial: this.levelNames[i] === "材质",
          };
          this.levelInfo.push(levelInfo);

          // 移动到下一级
          curLevel = this.getNextLevel(curLevel, this.getCurLevelValue(curLevel));
        }
      },
      // getter
      getCurLevelValue(level) {
        // 如果是等级规则数组
        if (level instanceof Array && level.length > 0) {
          return level[0].levelValue;
        }
        return null;
      },
      getLevelOptions(level) {
        return level === null ? [] : level?.map(l => l.levelValue);
      },
      getNextLevelName(index) {
        if (this.levelNames.length > index + 1) {
          return this.levelNames[index + 1];
        }
        return null;
      },
      //获取下一等级
      getNextLevel(curLevel, curLevelValue) {
        if (!curLevel) {
          return;
        }

        let nextLevel = null;
        // 获取下一级等级规则
        curLevel.some(level => {
          if (level.levelValue === curLevelValue) {
            nextLevel = level;
            return true;
          }
          return false;
        });

        return nextLevel?.nextLevel;
      },
      //获取材质信息
      getMaterialInfo() {
        let result = {};
        this.levelInfo?.forEach(level => {
          if (level.name === "材质") {
            result["材质"] = level.value;
            result["materialId"] = "";
          } else if (level.name === "性能等级") {
            result["性能等级"] = level.value;
          }
        })
        if (!result["材质"] || result["材质"] === "") {
          result["材质"] = "";
          result["materialId"] = "";
        }
        return result;
      },
      //更新属性值
      updateAttributeValue(primaryValue) {
        // 更新属性值
        // 通常是由于主属性变更会触发该函数
        let attrKeys = Object.keys(this.attributes);
        attrKeys.forEach(key => {
          let attribute = this.attributes[key];

          let attrNewValue;
          attribute.options.some(option => {
            if (option.primary === primaryValue) {
              // 选中该属性对应的主属性的第一个选项
              attrNewValue = option.options[0];
              return true;
            }
            return false;
          })

          // 如果属性是一个范围
          if (attribute.isInput) {
            this.selected[attribute.key] = this.parseRangeValue(attrNewValue, false);
          } else {
            this.selected[attribute.key] = attrNewValue;
          }
        });
      },
      changeSelectEventHandler(key) {
        // this.selected[key] = value;
        // this.selected.primary = value;
        // this.update();
        if (key == "primary") {
          this.updateAttributeValue(this.selected[key]);
        }
        // 把选中的信息传递给属性组件
        this.update();
        this.exeCommand(true);
      },
      //清除数据
      clearData() {
        this.params.reverseDirection = false;
        this.params.alignmentDir = "x";
        this.params.offsetDistance = 0;
        this.params.position.splice(0);
        this.params.direction.splice(0);
        this.switchQuery("position");
        fastenerDesignCommand.clearPreview();
      },
      //界面输入值改变时执行
      changeCommon() {
        this.exeCommand(true);
      },
      //确定
      confirm(){
        this.exeCommand(false);
        this.close();
      },
      //关闭
      close(){
        fastenerDesignCommand.closeActiveCmd();
      },
      //界面大小改变
      changePluginContainerHeight() {
        fastenerDesignCommand.changePluginContainerHeight({minWidth: this.$el.clientWidth, maxHeight: this.$el.clientHeight+10})
      },
      //取消选中实例的高亮
      removeSelect(item) {
        if (item) {
          let paramId = {
            instanceId: item.id,
            elementId: item.elementId
          }
          fastenerDesignCommand.clearHighLightInstanceElement(paramId);
        }
      },
      switchQuery(name) {
        for (const key in this.params.queryListActiveMap) {
          if (key === name){
            this.params.queryListActiveMap[key] = 1;
          }else{
            this.params.queryListActiveMap[key] = 0;
          }
        }
        let selectTypes = [ElementType.POINT, ElementType.DATUMPOINT, ElementType.ORIGINPOINT, ElementType.VERTEX, ElementType.EDGE];
        if (name === "direction") {
          selectTypes = [ElementType.FACE];
        }
        fastenerDesignCommand.setSelectType(selectTypes);
      },
    },
    mounted() {
      fastenerDesignCommand.init(500, 300, 500, () => {
        this.init();
        fastenerDesignCommand.handlePickElement(res => {
            res?.element?.forEach(data => {
              if (!data?.element) {
                return;
              }
              let objName = data.element.name;
              if (data?.instance?.name) {
                objName += "@" + data.instance.name;
              }
              if (this.params.queryListActiveMap.position === 1) {
                // if (element.type === ElementType.EDGE && !([GeomType.ARC, GeomType.CIRCLE].includes(element?.params?.type))) {
                //   return;
                // }
                //拾取点、基准点或者拾取圆弧线或者圆时执行
                //清除选择的位置对象重新添加
                if (!objName) {
                  objName = "基准点";
                }
                let objectInfo = {};
                if (data?.element.type === ElementType.EDGE) {
                  objectInfo = {
                    id: data?.instance?.id,
                    elementId: data?.element?.id,
                    name: objName,
                    elementType: data?.element?.type,
                  }
                } else {
                  objectInfo = {
                    id: data?.element?.id,
                    name: objName,
                    position: data?.element?.params?.position,
                  }
                }
                this.params.position.splice(0);
                this.params.position.push(objectInfo);
                //将对齐方向的选择设置为活动拾取列表对象
                this.switchQuery("direction");
                this.exeCommand(true);
              } else if (this.params.queryListActiveMap.direction === 1) {
                //拾取实例上的面时执行
                let objectInfo = {
                  id: data?.instance?.id,
                  elementId: data?.element?.id,
                  name: objName,
                  elementType: data?.element?.type,
                }
                this.params.direction.splice(0);
                this.params.direction.push(objectInfo);
                this.exeCommand(true);
              }
            });
        })
      })
    },
    computed: {
      getPrimaryAttributeAlias() {
        return this.primaryAttribute?.alias ?? "";
      }
    },
    watch: {
      curStandard () {
        this.getCategoryName();
      },

      curCategory() {
        this.getClassName();
      },

      curClass() {
        this.getComponentInfo();
      },

      curComponent() {
        this.getComponentData();
      },

      'partInfo': {
        handler(newValue) {
          if (!newValue){
            return;
          }
          this.attributes = {};
          this.parsePartInfo(newValue);
          // 解析材质信息
          this.parseComponentMaterialInfo();
        },
        immediate: true,
      },
    },
  }
</script>
<style scoped>
  .wrap {
    font-size: 12px;
  }

  select, input {
    outline: none;
    border: none;
  }

  .item {
    color: var(--text-color1);
    margin: 10px auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
  }

  .item select, .item input:hover {
    border-bottom: 1px solid var(--border-color5);
  }

  .item input {
    border-bottom: 1px solid var(--border-color3);
  }

  .item select, .item input {
    color: var(--text-color1);
    background-color: transparent;
    width: 150px;
  }

  .item select option {
    color: var(--text-color2);
    background-color: var(--bg-color2);
  }

  input.item {
    outline: none;
    border: none;
    color: var(--text-color1);
    background-color: var(--bg-color1);
    border-bottom: 1px solid var(--border-color3);
    text-align: center;
    height: 22px;
    width: 100%;
  }

  input.item:hover, input.item:focus {
    border-bottom: 1px solid var(--border-color5);
  }

  .select {
    position: relative;
  }

  .select input {
    position: absolute;
    width: 120px;
    left: 3px;
    border-bottom: none;
  }

  .select-item > span {
    text-align: left;
    width: 38px;
  }

  .attribute-unit {
    align-self: flex-end;
    @apply tw-ml-1;
  }

  .thumbnail-img {
    width: 100%;
    height: 130px;
    border: 1px solid var(--border-color1);
    @apply tw-h-full;
  }
</style>